<?php

namespace Transform;

abstract class Transform
{
    use FilterTrait;

    private $nullable = true;

    private function __construct(){}

    public function tran($arguments, $options)
    {
        if (empty($arguments) && is_array($arguments)) return [];

        // 列表判断，目前缺陷，$arguments的键不能是整型
        if (array_key_exists(0, $arguments)) {
            return array_map(function($argument) use ($options){
                return $this->transOne($argument, $options);
            }, $arguments);
        } else {
            return $this->transOne($arguments, $options);
        }
    }

    private function transOne($arguments, $options)
    {
        if (array_key_exists('allows', $options)) {
            $arguments = array_keep($arguments, $options['allows']);
        } else {
            // 排除未定义
            $arguments = array_intersect_key($arguments, $options);
        }
        foreach ($options as $field => $option) {
            if (!$this->nullable && is_null($arguments[$field])) continue;
            // 类型强转
            if (array_key_exists('type', $option)) settype($arguments[$field], $option['type']);
            // 重新赋值
            if (array_key_exists('value', $option)) $arguments[$field] = $option['value'];
            // 使用过滤方法
            if (array_key_exists('filters', $option)) {
                foreach ($option['filters'] as $filter) {
                    $arguments[$field] = $this->filter($filter, $arguments[$field]);
                }
            }
            if (array_key_exists('replaces', $option)) $arguments[$field] = $option['replaces'][$arguments[$field]];
            // 嵌套trans，注意死循环
            if (array_key_exists('trans', $option)) {
                $transOptions = $option['trans'];
                $transName = '\\Transform\\' . $transOptions['name'] . 'Transform';
                $column = isset($transOptions['column']) ? $option['column'] : $field;
                if (empty($arguments[$column])) break;
                $transInstance = new $transName();
                $value = $transInstance->trans($transOptions['method'], $arguments[$column]);
                $arguments[$field] = $value;
            }

            // 使用别名，须在最后执行
            if (array_key_exists('alias', $option)) {
                $arguments[$option['alias']] = $arguments[$field];
                unset($arguments[$field]);
            }
        }
        return $arguments;
    }

    public static function instance()
    {
        return new static();
    }

    private function filter(Filter $filter, $field)
    {
        if (method_exists($this, $filter->getMethod())) {
            return call_user_func_array([$this, $filter->getMethod()], [$field, $filter->getArgs()]);
            /* 因为function的参数位置不定，所以废除系统方法 */
        // } elseif (function_exists($filter->getMethod())) {
        //     return call_user_func_array($filter->getMethod(), $field);
        } else {
            throw new TransException("Filter [{$filter->getMethod()}] is undefined, check the FilterTrait!");
        }


    }

    public function trans($method, $arguments)
    {
        $instance = $this;
        $options = call_user_func_array([$instance, $method], [$arguments]);
        return call_user_func_array([$instance, 'tran'], [$arguments, $options]);
    }

    public function __call($method, $arguments) {
        if (count($arguments) > 0) $this->$method = $arguments[0];
        return $this;
    }
}
